package org.jivesoftware.smackx.filetransfer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
import org.jivesoftware.smack.filter.FromMatchesFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.packet.XMPPError.Condition;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.IBBExtensions.Close;
import org.jivesoftware.smackx.packet.IBBExtensions.Data;
import org.jivesoftware.smackx.packet.IBBExtensions.Open;
import org.jivesoftware.smackx.packet.StreamInitiation;

public class IBBTransferNegotiator extends StreamNegotiator
{
  public static final int DEFAULT_BLOCK_SIZE = 4096;
  protected static final String NAMESPACE = "http://jabber.org/protocol/ibb";
  private Connection connection;

  protected IBBTransferNegotiator(Connection paramConnection)
  {
    this.connection = paramConnection;
  }

  private void initInBandTransfer(IBBExtensions.Open paramOpen)
  {
    this.connection.sendPacket(FileTransferNegotiator.createIQ(paramOpen.getPacketID(), paramOpen.getFrom(), paramOpen.getTo(), IQ.Type.RESULT));
  }

  public void cleanup()
  {
  }

  public InputStream createIncomingStream(StreamInitiation paramStreamInitiation)
    throws XMPPException
  {
    return negotiateIncomingStream(initiateIncomingStream(this.connection, paramStreamInitiation));
  }

  public OutputStream createOutgoingStream(String paramString1, String paramString2, String paramString3)
    throws XMPPException
  {
    IBBExtensions.Open localOpen = new IBBExtensions.Open(paramString1, 4096);
    localOpen.setTo(paramString3);
    localOpen.setType(IQ.Type.SET);
    PacketCollector localPacketCollector = this.connection.createPacketCollector(new PacketIDFilter(localOpen.getPacketID()));
    this.connection.sendPacket(localOpen);
    IQ localIQ = (IQ)localPacketCollector.nextResult(SmackConfiguration.getPacketReplyTimeout());
    localPacketCollector.cancel();
    if (localIQ == null)
      throw new XMPPException("No response from peer on IBB open");
    IQ.Type localType = localIQ.getType();
    if (!(localType.equals(IQ.Type.RESULT)))
    {
      if (localType.equals(IQ.Type.ERROR))
        throw new XMPPException("Target returned an error", localIQ.getError());
      throw new XMPPException("Target returned unknown response");
    }
    return new IBBOutputStream(this, paramString3, paramString1, 4096);
  }

  public PacketFilter getInitiationPacketFilter(String paramString1, String paramString2)
  {
    PacketFilter[] arrayOfPacketFilter = new PacketFilter[2];
    arrayOfPacketFilter[0] = new FromContainsFilter(paramString1);
    arrayOfPacketFilter[1] = new IBBOpenSidFilter(paramString2);
    return new AndFilter(arrayOfPacketFilter);
  }

  public String[] getNamespaces()
  {
    String[] arrayOfString = new String[1];
    arrayOfString[0] = "http://jabber.org/protocol/ibb";
    return arrayOfString;
  }

  InputStream negotiateIncomingStream(Packet paramPacket)
    throws XMPPException
  {
    IBBExtensions.Open localOpen = (IBBExtensions.Open)paramPacket;
    if (localOpen.getType().equals(IQ.Type.ERROR))
      throw new XMPPException(localOpen.getError());
    IBBMessageSidFilter localIBBMessageSidFilter = new IBBMessageSidFilter(localOpen.getFrom(), localOpen.getSessionID());
    PacketFilter[] arrayOfPacketFilter = new PacketFilter[2];
    arrayOfPacketFilter[0] = new PacketTypeFilter(IBBExtensions.Close.class);
    arrayOfPacketFilter[1] = new FromMatchesFilter(localOpen.getFrom());
    AndFilter localAndFilter = new AndFilter(arrayOfPacketFilter);
    IBBInputStream localIBBInputStream = new IBBInputStream(this, localOpen.getSessionID(), localIBBMessageSidFilter, localAndFilter, null);
    initInBandTransfer(localOpen);
    return localIBBInputStream;
  }

  private class IBBInputStream extends InputStream
  implements PacketListener
  {
    private byte[] buffer;
    private int bufferPointer;
    private IQ closeConfirmation;
    private PacketCollector dataCollector;
    private boolean isClosed;
    private boolean isDone;
    private boolean isEOF;
    private Message lastMess;
    private int seq = -1;
    private String streamID;

    private IBBInputStream(, String paramString, PacketFilter paramPacketFilter1, PacketFilter paramPacketFilter2)
    {
      this.streamID = paramString;
      this.dataCollector = IBBTransferNegotiator.access$0(paramIBBTransferNegotiator).createPacketCollector(paramPacketFilter1);
      IBBTransferNegotiator.access$0(paramIBBTransferNegotiator).addPacketListener(this, paramPacketFilter2);
      this.bufferPointer = -1;
    }

    private void cancelTransfer()
    {
      cleanup();
      sendCancelMessage(paramMessage);
    }

    private void checkSequence(, int paramInt)
      throws IOException
    {
      if (this.seq == 65535)
        this.seq = -1;
      if (paramInt - 1 != this.seq)
      {
        cancelTransfer(paramMessage);
        throw new IOException("Packets out of sequence");
      }
      this.seq = paramInt;
    }

    private void cleanup()
    {
      this.dataCollector.cancel();
      IBBTransferNegotiator.access$0(this.this$0).removePacketListener(this);
    }

    private boolean loadBufferWait()
      throws IOException
    {
      Message localMessage = null;
      while (true)
      {
        int i;
        if (localMessage != null)
        {
          this.lastMess = localMessage;
          IBBExtensions.Data localData = (IBBExtensions.Data)localMessage.getExtension("data", "http://jabber.org/protocol/ibb");
          checkSequence(localMessage, (int)localData.getSeq());
          this.buffer = StringUtils.decodeBase64(localData.getData());
          this.bufferPointer = 0;
          i = 1;
        }
        while (true)
        {
          do
          {
            return i;
            if (!(this.isDone))
              break label80;
            localMessage = (Message)this.dataCollector.pollResult();
          }
          while (localMessage != null);
          i = 0;
        }
        label80: localMessage = (Message)this.dataCollector.nextResult(1000L);
      }
    }

    private void sendCancelMessage()
    {
      IQ localIQ = FileTransferNegotiator.createIQ(paramMessage.getPacketID(), paramMessage.getFrom(), paramMessage.getTo(), IQ.Type.ERROR);
      localIQ.setError(new XMPPError(XMPPError.Condition.remote_server_timeout, "Cancel Message Transfer"));
      IBBTransferNegotiator.access$0(this.this$0).sendPacket(localIQ);
    }

    private void sendCloseConfirmation()
    {
      IBBTransferNegotiator.access$0(this.this$0).sendPacket(this.closeConfirmation);
    }

    /**
     * @deprecated
     */
    public void close()
      throws IOException
    {
      monitorenter;
      try
      {
        boolean bool = this.isClosed;
        if (bool)
          monitorexit;
      }
      finally
      {
        while (true)
        {
          do
          {
            monitorexit;
            throw localObject;
          }
          while (this.lastMess == null);
          sendCancelMessage(this.lastMess);
        }
      }
    }

    public boolean markSupported()
    {
      return false;
    }

    public void processPacket()
    {
      if (((IBBExtensions.Close)paramPacket).getSessionID().equals(this.streamID))
      {
        this.isDone = true;
        this.closeConfirmation = FileTransferNegotiator.createIQ(paramPacket.getPacketID(), paramPacket.getFrom(), paramPacket.getTo(), IQ.Type.RESULT);
      }
    }

    /**
     * @deprecated
     */
    public int read()
      throws IOException
    {
      int i;
      label25: byte[] arrayOfByte;
      int j;
      monitorenter;
      try
      {
        if (!(this.isEOF))
        {
          boolean bool = this.isClosed;
          if (!(bool))
            break label25;
        }
        i = -1;
        monitorexit;
        return i;
        if ((this.bufferPointer == -1) || (this.bufferPointer >= this.buffer.length))
          loadBufferWait();
        arrayOfByte = this.buffer;
        j = this.bufferPointer;
        this.bufferPointer = (j + 1);
      }
      finally
      {
        monitorexit;
      }
    }

    /**
     * @deprecated
     */
    public int read()
      throws IOException
    {
      monitorenter;
      try
      {
        int i = read(paramArrayOfByte, 0, paramArrayOfByte.length);
        monitorexit;
        return i;
      }
      finally
      {
        localObject = finally;
        monitorexit;
        throw localObject;
      }
    }

    /**
     * @deprecated
     */
    public int read(, int paramInt1, int paramInt2)
      throws IOException
    {
      int i;
      monitorenter;
      try
      {
        if (!(this.isEOF))
        {
          boolean bool = this.isClosed;
          if (!(bool))
            break label29;
        }
        i = -1;
        while (true)
        {
          monitorexit;
          return i;
          label29: if (((this.bufferPointer != -1) && (this.bufferPointer < this.buffer.length)) || (loadBufferWait()))
            break;
          this.isEOF = true;
          i = -1;
        }
        if (paramInt2 - paramInt1 > this.buffer.length - this.bufferPointer)
          paramInt2 = this.buffer.length - this.bufferPointer;
        System.arraycopy(this.buffer, this.bufferPointer, paramArrayOfByte, paramInt1, paramInt2);
        this.bufferPointer = (paramInt2 + this.bufferPointer);
      }
      finally
      {
        monitorexit;
      }
    }
  }

  private static class IBBMessageSidFilter
  implements PacketFilter
  {
    private String from;
    private final String sessionID;

    public IBBMessageSidFilter(String paramString1, String paramString2)
    {
      this.from = paramString1;
      this.sessionID = paramString2;
    }

    public boolean accept(Packet paramPacket)
    {
      int i;
      if (!(paramPacket instanceof Message))
        i = 0;
      while (true)
      {
        while (true)
        {
          while (true)
          {
            return i;
            if (paramPacket.getFrom().equalsIgnoreCase(this.from))
              break;
            i = 0;
          }
          IBBExtensions.Data localData = (IBBExtensions.Data)paramPacket.getExtension("data", "http://jabber.org/protocol/ibb");
          if ((localData == null) || (localData.getSessionID() == null) || (!(localData.getSessionID().equalsIgnoreCase(this.sessionID))))
            break;
          i = 1;
        }
        i = 0;
      }
    }
  }

  private static class IBBOpenSidFilter
  implements PacketFilter
  {
    private String sessionID;

    public IBBOpenSidFilter(String paramString)
    {
      if (paramString == null)
        throw new IllegalArgumentException("StreamID cannot be null");
      this.sessionID = paramString;
    }

    public boolean accept(Packet paramPacket)
    {
      int i;
      if (!(IBBExtensions.Open.class.isInstance(paramPacket)))
        i = 0;
      while (true)
      {
        while (true)
        {
          return i;
          String str = ((IBBExtensions.Open)paramPacket).getSessionID();
          if ((str == null) || (!(str.equals(this.sessionID))))
            break;
          i = 1;
        }
        i = 0;
      }
    }
  }

  private class IBBOutputStream extends OutputStream
  {
    protected byte[] buffer;
    private final IQ closePacket;
    protected int count = 0;
    private String messageID;
    protected int seq = 0;
    private String sid;
    final String userID;

    IBBOutputStream(, String paramString1, String paramString2, int paramInt)
    {
      if (paramInt <= 0)
        throw new IllegalArgumentException("Buffer size <= 0");
      this.buffer = new byte[paramInt];
      this.userID = paramString1;
      this.messageID = new Message(paramString1).getPacketID();
      this.sid = paramString2;
      this.closePacket = createClosePacket(paramString1, paramString2);
    }

    private IQ createClosePacket(, String paramString2)
    {
      IBBExtensions.Close localClose = new IBBExtensions.Close(paramString2);
      localClose.setTo(paramString1);
      localClose.setType(IQ.Type.SET);
      return localClose;
    }

    /**
     * @deprecated
     */
    private void flushBuffer()
    {
      monitorenter;
      try
      {
        writeToXML(this.buffer, 0, this.count);
        this.count = 0;
        monitorexit;
        return;
      }
      finally
      {
        localObject = finally;
        monitorexit;
        throw localObject;
      }
    }

    private void writeOut(, int paramInt1, int paramInt2)
    {
      if (paramInt2 > this.buffer.length - this.count)
        flushBuffer();
      System.arraycopy(paramArrayOfByte, paramInt1, this.buffer, this.count, paramInt2);
      this.count = (paramInt2 + this.count);
    }

    /**
     * @deprecated
     */
    // ERROR //
    private void writeToXML(, int paramInt1, int paramInt2)
    {
      // Byte code:
      //   0: aload_0
      //   1: monitorenter
      //   2: aload_0
      //   3: new 95	java/lang/StringBuilder
      //   6: dup
      //   7: aload_0
      //   8: getfield 51	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:messageID	Ljava/lang/String;
      //   11: invokestatic 101	java/lang/String:valueOf	(Ljava/lang/Object;)Ljava/lang/String;
      //   14: invokespecial 102	java/lang/StringBuilder:<init>	(Ljava/lang/String;)V
      //   17: ldc 104
      //   19: invokevirtual 108	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
      //   22: aload_0
      //   23: getfield 31	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:seq	I
      //   26: invokevirtual 111	java/lang/StringBuilder:append	(I)Ljava/lang/StringBuilder;
      //   29: invokevirtual 114	java/lang/StringBuilder:toString	()Ljava/lang/String;
      //   32: invokevirtual 118	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:createTemplate	(Ljava/lang/String;)Lorg/jivesoftware/smack/packet/Message;
      //   35: astore 5
      //   37: new 120	org/jivesoftware/smackx/packet/IBBExtensions$Data
      //   40: dup
      //   41: aload_0
      //   42: getfield 53	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:sid	Ljava/lang/String;
      //   45: invokespecial 121	org/jivesoftware/smackx/packet/IBBExtensions$Data:<init>	(Ljava/lang/String;)V
      //   48: astore 6
      //   50: aload 5
      //   52: aload 6
      //   54: invokevirtual 125	org/jivesoftware/smack/packet/Message:addExtension	(Lorg/jivesoftware/smack/packet/PacketExtension;)V
      //   57: aload 6
      //   59: aload_1
      //   60: iload_2
      //   61: iload_3
      //   62: iconst_0
      //   63: invokestatic 131	org/jivesoftware/smack/util/StringUtils:encodeBase64	([BIIZ)Ljava/lang/String;
      //   66: invokevirtual 134	org/jivesoftware/smackx/packet/IBBExtensions$Data:setData	(Ljava/lang/String;)V
      //   69: aload 6
      //   71: aload_0
      //   72: getfield 31	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:seq	I
      //   75: i2l
      //   76: invokevirtual 138	org/jivesoftware/smackx/packet/IBBExtensions$Data:setSeq	(J)V
      //   79: aload_0
      //   80: monitorenter
      //   81: aload_0
      //   82: ldc2_w 139
      //   85: invokevirtual 145	java/lang/Object:wait	(J)V
      //   88: aload_0
      //   89: monitorexit
      //   90: aload_0
      //   91: getfield 24	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:this$0	Lorg/jivesoftware/smackx/filetransfer/IBBTransferNegotiator;
      //   94: invokestatic 149	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator:access$0	(Lorg/jivesoftware/smackx/filetransfer/IBBTransferNegotiator;)Lorg/jivesoftware/smack/Connection;
      //   97: aload 5
      //   99: invokevirtual 155	org/jivesoftware/smack/Connection:sendPacket	(Lorg/jivesoftware/smack/packet/Packet;)V
      //   102: iconst_1
      //   103: aload_0
      //   104: getfield 31	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:seq	I
      //   107: iadd
      //   108: ldc 156
      //   110: if_icmpne +29 -> 139
      //   113: iconst_0
      //   114: istore 10
      //   116: aload_0
      //   117: iload 10
      //   119: putfield 31	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:seq	I
      //   122: aload_0
      //   123: monitorexit
      //   124: return
      //   125: astore 8
      //   127: aload_0
      //   128: monitorexit
      //   129: aload 8
      //   131: athrow
      //   132: astore 4
      //   134: aload_0
      //   135: monitorexit
      //   136: aload 4
      //   138: athrow
      //   139: aload_0
      //   140: getfield 31	org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator$IBBOutputStream:seq	I
      //   143: istore 9
      //   145: iload 9
      //   147: iconst_1
      //   148: iadd
      //   149: istore 10
      //   151: goto -35 -> 116
      //   154: astore 7
      //   156: goto -68 -> 88
      //
      // Exception table:
      //   from	to	target	type
      //   81	88	125	finally
      //   88	90	125	finally
      //   127	129	125	finally
      //   2	81	132	finally
      //   90	122	132	finally
      //   129	132	132	finally
      //   139	145	132	finally
      //   81	88	154	java/lang/InterruptedException
    }

    public void close()
      throws IOException
    {
      flush();
      IBBTransferNegotiator.access$0(this.this$0).sendPacket(this.closePacket);
    }

    public Message createTemplate()
    {
      Message localMessage = new Message(this.userID);
      localMessage.setPacketID(paramString);
      return localMessage;
    }

    public void flush()
      throws IOException
    {
      flushBuffer();
    }

    public void write()
      throws IOException
    {
      if (this.count >= this.buffer.length)
        flushBuffer();
      byte[] arrayOfByte = this.buffer;
      int i = this.count;
      this.count = (i + 1);
      arrayOfByte[i] = (byte)paramInt;
    }

    public void write()
      throws IOException
    {
      write(paramArrayOfByte, 0, paramArrayOfByte.length);
    }

    /**
     * @deprecated
     */
    public void write(, int paramInt1, int paramInt2)
      throws IOException
    {
      monitorenter;
      try
      {
        if (paramInt2 >= this.buffer.length)
        {
          writeOut(paramArrayOfByte, paramInt1, this.buffer.length);
          write(paramArrayOfByte, paramInt1 + this.buffer.length, paramInt2 - this.buffer.length);
          monitorexit;
          return;
        }
      }
      finally
      {
        monitorexit;
      }
    }
  }
}